package ph.com.gs3.formalistics.model.facades;

import org.json.JSONException;
import org.json.JSONObject;

import ph.com.gs3.formalistics.global.constants.StarMark;
import ph.com.gs3.formalistics.global.utilities.DateUtilities;
import ph.com.gs3.formalistics.global.utilities.logging.FLLogger;
import ph.com.gs3.formalistics.model.LocalDataAccessObject.InsertFailedException;
import ph.com.gs3.formalistics.model.ldao.OutgoingActionsLDAO;
import ph.com.gs3.formalistics.model.vo.business.User;
import ph.com.gs3.formalistics.model.vo.business.document.Document;
import ph.com.gs3.formalistics.model.vo.business.document.OutgoingAction;
import ph.com.gs3.formalistics.model.vo.business.document.SubmitReadyAction;
import android.content.Context;

public class OutgoingActionDataWriter {

	public static final String TAG = OutgoingActionDataWriter.class.getSimpleName();

	private OutgoingActionsLDAO outgoingActionsLDAO;

	public OutgoingActionDataWriter(Context context) {

		outgoingActionsLDAO = new OutgoingActionsLDAO(context);

	}

	public OutgoingAction saveDocumentAction(int documentId, int formId,
	        JSONObject documentFieldValues, String action, User issuedByUser) {

		return saveDocumentAction(documentId, formId, documentFieldValues, action, issuedByUser, -1);

	}

	public OutgoingAction saveDocumentAction(int documentId, int formId,
	        JSONObject documentFieldValues, String action, User issuedByUser, int documentParentId) {

		OutgoingAction updatedAction = null;
		OutgoingAction existingAction = null;

		// Check if there is an already existing outgoing action
		try {
			outgoingActionsLDAO.open();
			// Throws JSONException
			existingAction = outgoingActionsLDAO.getOutgoingActionByDocumentId(documentId);

			if (existingAction == null) {
				// Create new action
				// Throws InsertFailedException
				updatedAction = createAndSaveNewOutgoingAction(documentId, formId,
				        documentFieldValues, action, null, issuedByUser, documentParentId);
			} else {
				// Update the existing action
				int actionId = existingAction.getId();
				updatedAction = outgoingActionsLDAO.updateOutgoingAction(actionId,
				        documentFieldValues, action, documentParentId);
			}

		} catch (JSONException | InsertFailedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} finally {
			outgoingActionsLDAO.close();
		}

		return updatedAction;

	}

	public OutgoingAction saveStarMark(int documentId, int formId, StarMark starMark,
	        User issuedByUser) {

		OutgoingAction updatedAction = null;
		OutgoingAction existingAction = null;

		// Check if there is an already existing outgoing action
		try {
			outgoingActionsLDAO.open();
			// Throws JSONException
			existingAction = outgoingActionsLDAO.getOutgoingActionByDocumentId(documentId);

			if (existingAction == null) {
				// Create new action
				// Throws InsertFailedException
				updatedAction = createAndSaveNewOutgoingAction(documentId, formId, null,
				        SubmitReadyAction.ACTION_NO_DOCUMENT_SUBMISSION, starMark, issuedByUser, -1);
			} else {
				// Update the existing action
				int actionId = existingAction.getId();
				int isStarred = starMarkToCode(starMark);
				updatedAction = outgoingActionsLDAO.updateOutgoingActionStar(actionId, isStarred);
			}

			return updatedAction;

		} catch (JSONException | InsertFailedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} finally {
			outgoingActionsLDAO.close();
		}

	}

	/**
	 * Creates a new outgoing action in the database, this methods assumes a connected
	 * database already.
	 * 
	 * @param documentId
	 * @param formId
	 * @param documentFieldValues
	 * @param action
	 * @param starMark
	 * @param issuedByUser
	 * @return
	 * @throws InsertFailedException
	 * @throws JSONException
	 */
	public OutgoingAction createAndSaveNewOutgoingAction(int documentId, int formId,
	        JSONObject documentFieldValues, String action, StarMark starMark, User issuedByUser,
	        int parentDocumentId) throws InsertFailedException, JSONException {

		OutgoingAction newAction = new OutgoingAction();
		OutgoingAction savedAction = null;

		Document emptyDocument = new Document();
		emptyDocument.setId(documentId);

		String dateIssued = DateUtilities.getServerFormattedCurrentDate();

		newAction.setAction(action);
		newAction.setDocumentFieldUpdates(documentFieldValues);
		newAction.setDocument(emptyDocument);
		newAction.setFormId(formId);
		newAction.setIssuedByUser(issuedByUser);
		newAction.setIsStarredCode(starMarkToCode(starMark));
		newAction.setDateIssued(dateIssued);
		newAction.setParentDocumentId(parentDocumentId);

		savedAction = outgoingActionsLDAO.saveOutgoingAction(newAction);

		return savedAction;

	}

	public int starMarkToCode(StarMark starMark) {

		int starCode;

		if (starMark == StarMark.STARRED) {
			starCode = SubmitReadyAction.STAR_MARK_CODE_STAR;
		} else if (starMark == StarMark.UNSTARRED) {
			starCode = SubmitReadyAction.STAR_MARK_CODE_UNSTAR;
		} else {
			starCode = SubmitReadyAction.STAR_MARK_CODE_NO_ACTION;
		}

		return starCode;

	}

	public void clearOrphanedOutgoingActions() {

		FLLogger.d(TAG, "clearOrphanedOutgoingActions");

		try {
			outgoingActionsLDAO.open();
			outgoingActionsLDAO.clearOrphanedOutgoingActions();
		} finally {
			outgoingActionsLDAO.close();
		}

	}

	public void updateChildOutgoingActionsForSubmition(int parentDocumentId) {

		try {
			outgoingActionsLDAO.open();
			outgoingActionsLDAO.updateChildOutgoingActionsForSubmition(parentDocumentId);
		} finally {
			outgoingActionsLDAO.close();
		}

	}

}
